import copy

class cvm:
    code = [] # byte code representing the program
    ic = 0 # current instruction  
    ifaces = [] # interface tables 
    stk = [] # primary evaluation stack 
    aux = [] # auxiliary evaluation stack
    events = [] # event queue

    # Clone

    def clone(self, x):
        if type(x) is InstanceType:
            return copy.deepcopy(x)
        else:
            return copy.copy(x)
        
    # Opcode implementations 
    
    def op_noop(self):
        ic = ic # do nothing 
                            
    def op_add(self):
        stk.append(stk.pop() + stk.pop())

    def op_mult(self):
        stk.append(stk.pop() * stk.pop())
    
    def op_pop(self):
        stk.pop()

    def op_dup(self):
        top = stk.pop()
        stk.append(top)
        stk.append(clone(top))

    def op_swap(self):
        top = stk.pop()
        nxt = stk.pop()
        stk.append(top)
        stk.append(nxt)
    
    def op_push_short(self):
        stk.append(code[ic] << 8)
        ic += 1
        stk.append(code[ic])
        op_add(self)		
    
    def op_apply(self):
        aux.append(ic)
        op_tail_apply(self)

    def op_tail_apply(self):
        ic = stk.pop()

    def op_ret(self):
        ic = aux.pop()

    def op_save_cont(self):
        stk.append(clone(self))

    def op_run_cont(self):
        cont = stk.pop();
        cont.run(self);

    # Used to dispatch op-codes to actual implementations
    
    dispatch_array =	[
        op_noop,
        op_add,
        op_push_short,
        op_apply,
        op_save_continuation,
        op_run_continuation,
        op_shl,
        op_shr]
            
    def dispatch(self):
        cur = code[ic]
        ic += 1
        dispatch_array(self)
            
    
    
    
    
